/* GoCart Factory
* Yudong Yi
* Desc: Will generate a GoCart ride & track that will have a simple animation.
* 
*/
#include "StdAfx.h"
#include "SgObject.h"
#include "GoCartFactory.h"
#include "SgMaterial.h"
#include "SgComposite.h"
#include "SgPolygon.h"
#include "SgRegularPolygon.h"
#include "SgRegularCylinder.h"
#include "SgRotateAroundPoint.h"
#include "SgTranslate.h"
#include "SgTransform.h"
#include "AnimationRotateGoCart.h"
#include "AnimationTranslateGoCart.h"
#include "SgBox.h"
#ifndef M_PI
#define M_PI 3.14159265358979323846
#endif
CGoCartFactory::CGoCartFactory(void)
{
	tireTextMiddle = new CSgTexture(L"tireMiddle.bmp");
	rimText = new CSgTexture(L"rim.bmp");
	usaFlag = new CSgTexture(L"usaFlag.bmp");
	fireText = new CSgTexture(L"fire.bmp");
	racingFlagText = new CSgTexture(L"racingFlag.bmp");
	stageText1 = new CSgTexture(L"stageText.bmp");
	carWindowText = new CSgTexture(L"windowText.bmp");
	carBodyText = new CSgTexture(L"carBodyText.bmp");
}

CGoCartFactory::~CGoCartFactory(void)
{
}

/*
 * Name: Create()
 * Description: Creates the round up ride
 * Parameters: root - the root node of the scene graph to attach to
 */
void CGoCartFactory::Create(CSgComposite *root)
{
	m_root = root;
	CSgPtr <CSgTranslate> GoCart = new CSgTranslate(35, 0.1, -20);
	m_root->AddChild(GoCart);
	CreateTrack(GoCart);
	CreateStage(GoCart);
	CreateCart(GoCart);

}

void CGoCartFactory::CreateCart(CSgComposite *parent)
{
	CSgPtr<CSgTranslate> transformCart = new CSgTranslate(-28,1,3.5);
	CSgPtr<CSgTranslate> transformToStart = new CSgTranslate(0,0,0);
	parent->AddChild(transformCart);


	CSgPtr<CSgTranslate> goStraight = new CSgTranslate(0,0,0);
	CSgPtr<CSgRotateAroundPoint> turn = new CSgRotateAroundPoint();
	turn->SetNormal(0,1,0);
	turn->SetAngle(0);
	turn->SetPoint(CGrVector(0,0,0));
	goStraight->AddChild(turn);
	turn->AddChild(transformToStart);

	CSgPtr<CAnimationRotateGoCart> animationTurn = new CAnimationRotateGoCart();
	CSgPtr<CAnimationTranslateGoCart> animationStraight = new CAnimationTranslateGoCart();

											//Considering the heavy CPU/Graphic load of our program,
											// Plus the car is moving fast enough to ignore
											// the rotation of the wheels, So i didn't do 
											// the rotation animation of the wheels
	animationTurn->SetNode(turn);
	animationStraight->SetNode(goStraight);
	m_timeline->AddChannel(animationTurn);  //Animation Turn.
	m_timeline->AddChannel(animationStraight);  //Animation Go Straight.
	transformCart->AddChild(goStraight);
	

	//------------------------------- Cart Body ----------------------
	CSgPtr <CSgTranslate> transformToBody = new CSgTranslate(-2,-0.3,0);
	transformToStart->AddChild(transformToBody);
	CSgPtr <CSgMaterial> mainColor = new CSgMaterial();
	mainColor->SetDiffuseColor(1.0f,0.98f,0.98f, 1.0f );
	mainColor->SetSpecularColor(0.0f,0.0f,0.0f, 1.0f );
	CSgPtr <CSgMaterial> frontColor = new CSgMaterial();
	frontColor->SetDiffuseColor(1.0f,0.98f,0.98f, 1.f );
	frontColor->SetSpecularColor(0.0f,0.0f,0.0f, 1.f );

	
	//main
	transformToBody->AddChild(mainColor);
	CSgPtr <CSgBox> main = new CSgBox(6, 1, 2);
	mainColor->AddChild(carBodyText);
	carBodyText->AddChild(main);

	//Engine room
	CSgPtr <CSgPolygon> engineTop = new CSgPolygon();
	racingFlagText->AddChild(engineTop);
	CSgPtr <CSgPolygon> engineRight = new CSgPolygon();
	CSgPtr <CSgPolygon> engineLeft = new CSgPolygon();
	CSgPtr <CSgPolygon> engineBack = new CSgPolygon();
	CSgPtr <CSgPolygon> engineFront = new CSgPolygon();
	CSgPtr <CSgPolygon> engineBottom = new CSgPolygon();
	CSgPtr <CSgTranslate> transformToFront = new CSgTranslate(6,0,-1);
	transformToFront->AddChild(frontColor);
	frontColor->AddChild(racingFlagText);
	frontColor->AddChild(engineRight);
	frontColor->AddChild(engineLeft);
	frontColor->AddChild(engineBack);
	frontColor->AddChild(engineFront);
	frontColor->AddChild(engineBottom);
	transformToBody->AddChild(transformToFront);
	double	a[]={0,1,0},b[]={0,1,2},c[]={2,0.5,1.5},d[]={2,0.5,0.5},
		e[]={0,0,2},f[]={2,0,1.5},g[]={0,0,0},h[]={2,0,0.5};
	double *n=Normal3dv(a,b,c); //top
	engineTop->AddNormal(CGrVector(n[0],n[1],n[2],1));
	engineTop->AddVertex3dv(a);
	engineTop->AddTexCoord(CGrVector(1,1));
	engineTop->AddVertex3dv(b);
	engineTop->AddTexCoord(CGrVector(0,1));
	engineTop->AddVertex3dv(c);
	engineTop->AddTexCoord(CGrVector(0,0));
	engineTop->AddVertex3dv(d);
	engineTop->AddTexCoord(CGrVector(1,0));
	delete [] n; 
	
	n=Normal3dv(b,e,f); //near
	engineRight->AddNormal(CGrVector(n[0],n[1],n[2],1));
	engineRight->AddVertex3dv(b);
	engineRight->AddVertex3dv(e);
	engineRight->AddVertex3dv(f);
	engineRight->AddVertex3dv(c);
	delete [] n;
	n=Normal3dv(a,d,h); //far
	engineLeft->AddNormal(CGrVector(n[0],n[1],n[2],1));
	engineLeft->AddVertex3dv(a);
	engineLeft->AddVertex3dv(d);
	engineLeft->AddVertex3dv(h);
	engineLeft->AddVertex3dv(g);
	delete [] n;
	engineBack->AddNormal(CGrVector(1,0,0,1));
	engineBack->AddVertex3dv(c);
	engineBack->AddVertex3dv(f);
	engineBack->AddVertex3dv(h);
	engineBack->AddVertex3dv(d);
	engineFront->AddNormal(CGrVector(-1,0,0,1));
	engineFront->AddVertex3dv(a);
	engineFront->AddVertex3dv(g);
	engineFront->AddVertex3dv(e);
	engineFront->AddVertex3dv(b);
	engineBottom->AddNormal(CGrVector(0,-1,0,1));
	engineBottom->AddVertex3dv(e);
	engineBottom->AddVertex3dv(g);
	engineBottom->AddVertex3dv(h);
	engineBottom->AddVertex3dv(f);
	
	//Side fenders
	CSgPtr <CSgTranslate> transformToSide = new CSgTranslate(4.3,0.5,1);
	CSgPtr <CSgRotateAroundPoint> rotateSide = new CSgRotateAroundPoint();
	rotateSide->SetNormal(0,0,1);
	rotateSide->SetAngle(90);
	rotateSide->SetPoint(0,0,0);
	transformToSide->AddChild(rotateSide);
	CSgPtr <CSgMaterial> sideColor = new CSgMaterial();
	sideColor->SetDiffuseColor(1.0f,1.0f,1.0f, 1.0f );
	sideColor->SetSpecularColor(0.0f,0.0f,0.0f, 1.f );
	rotateSide->AddChild(sideColor);
	transformToBody->AddChild(transformToSide);

	CSgPtr <CSgRegularCylinder> sideFenderLeft = new CSgRegularCylinder(); //Tire texture.
	sideFenderLeft->SetProperties(20,2,0.3);

	sideColor->AddChild(fireText);
	fireText->AddChild(sideFenderLeft);
	CSgPtr <CSgTranslate> transformToSideLeft = new CSgTranslate(0,0.0,-2);
	transformToSideLeft->AddChild(transformToSide);
	transformToBody->AddChild(transformToSideLeft);

	//--------Driver's room------------
	CSgPtr <CSgMaterial> driverColor = new CSgMaterial();
	driverColor->SetDiffuseColor(1.0f,1.0f,1.0f, 1.0f  );
	driverColor->SetSpecularColor(0.0f,0.0f,0.0f, 1.0f );
	
	
	CSgPtr <CSgBox> driverBack = new CSgBox(2,0.5,2); //Back
	CSgPtr <CSgTranslate> transformToDriverBack = new CSgTranslate(0,1,0);
	transformToDriverBack->AddChild(driverColor);
	transformToBody->AddChild(transformToDriverBack);
	usaFlag->AddChild(driverBack);
	transformToDriverBack->AddChild(usaFlag);



	//--------------Windows-------------
	CSgPtr<CSgMaterial> windowColor = new CSgMaterial(); //Defualt color of windows
	windowColor->SetDiffuseColor(1.0f,1.0f,1.0f,1.0f);
	windowColor->SetSpecularColor(0.0f,0.0f,0.0f, 1.0f );
	windowColor->SetShininess(0.8f);
	transformToBody->AddChild(carWindowText);
	carWindowText->AddChild(windowColor);

	CSgPtr <CSgTranslate> transformToDriverBackWin = new CSgTranslate(2.0,1,0);//Back Window
	CSgPtr <CSgPolygon> driverBackWin = new CSgPolygon(); 
	driverBackWin->AddNormal(CGrVector(-1,0,0));
	driverBackWin->AddVertex3d(0,1,-0.7);
	driverBackWin->AddTexCoord(CGrVector(0,1));
	driverBackWin->AddVertex3d(0,0.5,-1);
	driverBackWin->AddTexCoord(CGrVector(0,0));
	driverBackWin->AddVertex3d(0,0.5,1);
	driverBackWin->AddTexCoord(CGrVector(1,0));
	driverBackWin->AddVertex3d(0,1,0.7);
	driverBackWin->AddTexCoord(CGrVector(1,1));
	windowColor->AddChild(transformToDriverBackWin);
	transformToDriverBackWin->AddChild(driverBackWin);



	CSgPtr <CSgTranslate> transformToDriverTop = new CSgTranslate(2.0,1,0);//Top Window
	CSgPtr <CSgPolygon> driverTop = new CSgPolygon(); 
	driverTop->AddNormal(CGrVector(0,-1,0));
	driverTop->AddVertex3d(0,1,-0.7);
//	driverTop->AddTexCoord(CGrVector());
	driverTop->AddVertex3d(0,1,0.7);
//	driverTop->AddTexCoord(CGrVector());
	driverTop->AddVertex3d(1,1,0.7);
//	driverTop->AddTexCoord(CGrVector());
	driverTop->AddVertex3d(1,1,-0.7);
//	driverTop->AddTexCoord(CGrVector());
	windowColor->AddChild(transformToDriverTop);
	transformToDriverTop->AddChild(driverTop);

	
	CSgPtr <CSgPolygon> driverFrontA = new CSgPolygon(); //Front Window
	driverFrontA->AddNormal(CGrVector(0.5,0.5,0));	
	driverFrontA->AddVertex3dv(CGrVector(-3.0,1,0.7));
	driverFrontA->AddTexCoord(CGrVector(0,1));
	driverFrontA->AddVertex3dv(CGrVector(0,0,1));
	driverFrontA->AddTexCoord(CGrVector(0,0));
	driverFrontA->AddVertex3dv(CGrVector(0,0,-1));
	driverFrontA->AddTexCoord(CGrVector(1,0));
	driverFrontA->AddVertex3dv(CGrVector(-3.0,1,-0.7));
	driverFrontA->AddTexCoord(CGrVector(1,1));
	CSgPtr <CSgTranslate> transformToDriverFrontA = new CSgTranslate(6,1,0);
	windowColor->AddChild(transformToDriverFrontA);
	transformToDriverFrontA->AddChild(driverFrontA);

	CSgPtr <CSgPolygon> driverFrontRA = new CSgPolygon();//Right Window
	driverFrontRA->AddNormal(CGrVector(0,0.2,-0.6));	
	driverFrontRA->AddVertex3dv(CGrVector(0,0,1));
	driverFrontRA->AddVertex3dv(CGrVector(-3,1,0.7));
	driverFrontRA->AddVertex3dv(CGrVector(-4,1,0.7));
	driverFrontRA->AddVertex3dv(CGrVector(-4,0,1));
	windowColor->AddChild(transformToDriverFrontA);
	transformToDriverFrontA->AddChild(driverFrontRA);


	CSgPtr <CSgPolygon> driverFrontL = new CSgPolygon(); //Left Window
	driverFrontL->AddNormal(CGrVector(0,0,-1));	
	driverFrontL->AddVertex3dv(CGrVector(-4,0,-1));
	driverFrontL->AddVertex3dv(CGrVector(-4,1,-0.7));
	driverFrontL->AddVertex3dv(CGrVector(-3,1,-0.7));
	driverFrontL->AddVertex3dv(CGrVector(0,0,-1));
	windowColor->AddChild(transformToDriverFrontA);
	transformToDriverFrontA->AddChild(driverFrontL);




	//-----------------------------   Tires   -----------------------------

	        // -------------  Make the tire -------------

	CSgPtr <CSgRotateAroundPoint> pTire = new CSgRotateAroundPoint();
	pTire->SetAngle(90);
	pTire->SetPoint(0.0,0.0,0.0);
	pTire->SetNormal(1,0,0);
	CSgPtr<CSgMaterial> tireColor = new CSgMaterial(); //Defualt color of tire
	tireColor->SetDiffuseColor(0.466f, 0.533f, .6f, 1.f );
	tireColor->SetSpecularColor(0.0f, 0.0f, .0f, 1.f );
	pTire->AddChild(tireColor);
	pTire->AddChild(tireTextMiddle);
	CSgPtr <CSgMesh> tireMiddle = new CSgMesh(); //Tire texture.
	tireTextMiddle->AddChild(tireMiddle);
	CSgPtr <CSgMesh> tire = new CSgMesh();
	tireColor->AddChild(tire);
	CSgPtr <CSgPolygon> rimA = new CSgPolygon();
	CSgPtr <CSgPolygon> rimB = new CSgPolygon();
	rimA->AddNormal(CGrVector(0,-1,0));
	rimA->AddVertex3d(-0.7,1.01,-0.7);
	rimA->AddTexCoord(CGrVector(0,0));
	rimA->AddVertex3d(-0.7,1.01,0.7);
	rimA->AddTexCoord(CGrVector(0,1));
	rimA->AddVertex3d(0.7,1.01,0.7);
	rimA->AddTexCoord(CGrVector(1,1));
	rimA->AddVertex3d(0.7,1.01,-0.7);
	rimA->AddTexCoord(CGrVector(1,0));
	rimText->AddChild(rimA);
	
	rimB->AddNormal(CGrVector(0,1,0));
	rimB->AddVertex3d(0.7,-0.01,-0.7);
	rimB->AddTexCoord(CGrVector(1,0));
	rimB->AddVertex3d(0.7,-0.01,0.7);
	rimB->AddTexCoord(CGrVector(1,1));
	rimB->AddVertex3d(-0.7,-0.01,0.7);
	rimB->AddTexCoord(CGrVector(0,1));
	rimB->AddVertex3d(-0.7,-0.01,-0.7);
	rimB->AddTexCoord(CGrVector(0,0));
	rimText->AddChild(rimB);	
	
	tireColor->AddChild(rimText);
	double inX1=0,inX2=0,inY1=0,inY2=0,
		   outX1=0,outY1=10,outX2=0,outY2=10;
	for(int i=0;i<50;i++)
	{   //Compute vertex on the circle.
		outX1 =  0 + 1 * sin((2*M_PI/50)*i); 
		outY1 = 0 + 1 * cos((2*M_PI/50)*i);
		outX2 =  0 + 1 * sin((2*M_PI/50)*(i+1)); 
		outY2 = 0 + 1 * cos((2*M_PI/50)*(i+1));
		inX1= 0 + 0.4 * sin((2*M_PI/50)*i);  
		inY1= 0 + 0.4 * cos((2*M_PI/50)*i); 
		inX2= 0 + 0.4 * sin((2*M_PI/50)*(i+1));
		inY2= 0 + 0.4 * cos((2*M_PI/50)*(i+1));

		//Outer side
		tire->AddNormal(CGrVector(0, -1, 0));
	    tire->AddVertex(CGrVector(outX1, 1, outY1));
		tire->AddVertex(CGrVector(outX2, 1, outY2));
		tire->AddVertex(CGrVector(inX2, 1, inY2));
		tire->AddVertex(CGrVector(inX1, 1, inY1));
		
		//Inner side
		tire->AddNormal(CGrVector(0, 1, 0));
		tire->AddVertex(CGrVector(inX1, 0, inY1));
		tire->AddVertex(CGrVector(inX2, 0, inY2));
		tire->AddVertex(CGrVector(outX2, 0, outY2));
		tire->AddVertex(CGrVector(outX1, 0, outY1));

		//Texture of tire
		tireMiddle->AddNormal(CGrVector(outX1, 0, outY1));
		//First half of triangle
		tireMiddle->AddVertex(CGrVector(outX1, 1, outY1));
		tireMiddle->AddTexCoord(CGrVector(0,0));
		tireMiddle->AddVertex(CGrVector(outX1, 0, outY1));
		tireMiddle->AddTexCoord(CGrVector(1,0));
		tireMiddle->AddVertex(CGrVector(outX2, 0, outY2));
		tireMiddle->AddTexCoord(CGrVector(1,1));
		//Second half of triangle
		tireMiddle->AddVertex(CGrVector(outX2, 0, outY2));
		tireMiddle->AddTexCoord(CGrVector(1,1));
		tireMiddle->AddVertex(CGrVector(outX2, 1, outY2));
		tireMiddle->AddTexCoord(CGrVector(0,1));
		tireMiddle->AddVertex(CGrVector(outX1, 1, outY1));
		tireMiddle->AddTexCoord(CGrVector(0,0));
		
	}
	for(int i=0;i<400; i +=4) 
	{
		tire->AddFlatQuad(i, i+1, i+2, i+3, i/4);
	}
	for(int i=0;i<300; i+=6)
	{
		tireMiddle->AddTriangleVertex(i,i/6,i);
		tireMiddle->AddTriangleVertex(i+1,i/6,i+1);
		tireMiddle->AddTriangleVertex(i+2,i/6,i+2);
		tireMiddle->AddTriangleVertex(i+3,i/6,i+3);
		tireMiddle->AddTriangleVertex(i+4,i/6,i+4);
		tireMiddle->AddTriangleVertex(i+5,i/6,i+5);
	}

	// ------------------- Make Axis & stand of tires. --------------
	CSgPtr <CSgMaterial> cylinderColor = new CSgMaterial();
	cylinderColor->SetDiffuseColor(0.82f, 0.82f, 0.82f, 1.f );
	cylinderColor->SetSpecularColor(0.0f, 0.0f, 0.0f, 1.f );
	
	CSgPtr <CSgRegularCylinder> cylinderTireStandA = new CSgRegularCylinder(); //Cylinder connect car & tires.
	cylinderTireStandA->SetProperties(10,0.5,0.1);
	CSgPtr <CSgRegularCylinder> cylinderTireStandB = new CSgRegularCylinder(); //Cylinder connect car & tires.
	cylinderTireStandB->SetProperties(10,0.7,0.06);

	// -------------------- Assemble tires onto the cart ----------

	CSgPtr <CSgRotateAroundPoint> rotateCylinder = new CSgRotateAroundPoint(); 
	rotateCylinder->SetAngle(90);
	rotateCylinder->SetPoint(0.0,0.0,0.0);
	rotateCylinder->SetNormal(1,0,0);
	rotateCylinder->AddChild(cylinderTireStandA);

	CSgPtr<CSgTranslate> transformToRightCylinder = new CSgTranslate(0,0,0.5);
	CSgPtr <CSgRotateAroundPoint> rotateToRightCylinder = new CSgRotateAroundPoint();
	rotateToRightCylinder->SetAngle(-45);
	rotateToRightCylinder->SetPoint(0.0,0.0,0.0);
	rotateToRightCylinder->SetNormal(1,0,0);
	rotateToRightCylinder->AddChild(cylinderTireStandB);
	transformToRightCylinder->AddChild(rotateToRightCylinder);

	CSgPtr <CSgRotateAroundPoint> rotateToLeftCylinder = new CSgRotateAroundPoint();
	rotateToLeftCylinder->SetAngle(45);
	rotateToLeftCylinder->SetPoint(0.0,0.0,0.0);
	rotateToLeftCylinder->SetNormal(1,0,0);
	rotateToLeftCylinder->AddChild(cylinderTireStandB);

	CSgPtr<CSgTranslate> transformToFrontLefCy = new CSgTranslate(3.5,0,-1.5);
	CSgPtr<CSgTranslate> transformToFrontLefTire = new CSgTranslate(3.5,0,-2.5); //Front Left Tire
	transformToStart->AddChild(transformToFrontLefTire);
	transformToFrontLefTire->AddChild(pTire);

	CSgPtr<CSgTranslate> transformToFrontRightCy = new CSgTranslate(3.5,0,1.0);
	CSgPtr<CSgTranslate> transformToFrontRighTire = new CSgTranslate(3.5,0,1.5); //Front Right
	transformToStart->AddChild(transformToFrontRighTire);
	transformToFrontRighTire->AddChild(pTire);

	CSgPtr<CSgTranslate> transformToBackLeftCy = new CSgTranslate(-0.8,0,-1.5);
	CSgPtr<CSgTranslate> transformToBackLefTire = new CSgTranslate(-0.8,0,-2.5); //Back Left
	transformToStart->AddChild(transformToBackLefTire);
	transformToBackLefTire->AddChild(pTire);

	CSgPtr<CSgTranslate> transformToBackRightCy = new CSgTranslate(-0.8,0,1.0);
	CSgPtr<CSgTranslate > transformToBackRightTire = new CSgTranslate(-0.8,0,1.5); // Back right
	transformToStart->AddChild(transformToBackRightTire);
	transformToBackRightTire->AddChild(pTire);

	
	transformToFrontLefCy->AddChild(rotateCylinder);
	transformToFrontLefCy->AddChild(rotateToLeftCylinder);

	transformToFrontRightCy->AddChild(rotateCylinder);
	transformToFrontRightCy->AddChild(transformToRightCylinder);

	transformToBackLeftCy->AddChild(rotateCylinder);
	transformToBackLeftCy->AddChild(rotateToLeftCylinder);

	transformToBackRightCy->AddChild(rotateCylinder);
	transformToBackRightCy->AddChild(transformToRightCylinder);
	cylinderColor->AddChild(transformToFrontLefCy);
	cylinderColor->AddChild(transformToFrontRightCy);
	cylinderColor->AddChild(transformToBackLeftCy);
	cylinderColor->AddChild(transformToBackRightCy);
	transformToStart->AddChild(cylinderColor);
}

void CGoCartFactory::CreateStage(CSgComposite *parent)
{
	//Stage for second place
	CSgPtr<CSgMaterial> stageColor = new CSgMaterial();
	stageColor->SetDiffuseColor(1.f, 1.f, 1.f, 1.f);
	stageColor->SetSpecularColor(0.f, 0.f, 0.f, 1.f);
	parent->AddChild(stageColor);
	CSgPtr<CSgTranslate > transformToStage = new CSgTranslate(-5,0,-5);
	stageColor->AddChild(stageText1);
	stageText1->AddChild(transformToStage);
	CSgPtr<CSgBox> stageSecond = new CSgBox(4, 1, 2);
	transformToStage->AddChild(stageSecond);

	//Stage for first place
	CSgPtr<CSgTranslate> transformToStageMiddle = new CSgTranslate();
	transformToStageMiddle->SetProperties(2,1,0);
	transformToStage->AddChild(transformToStageMiddle);
	CSgPtr<CSgBox> stageMiddle = new CSgBox(2, 0.5, 2);
	transformToStageMiddle->AddChild(stageMiddle);
	//Stage for third place
	CSgPtr<CSgTranslate> transformToStageThird = new CSgTranslate();
	stageText1->AddChild(transformToStageThird);
	transformToStageThird->SetProperties(-1,0,-5);
	CSgPtr<CSgBox> stageTop = new CSgBox(2, 0.5, 2);
	transformToStageThird->AddChild(stageTop);

}
void CGoCartFactory::CreateTrack(CSgComposite *parent)
{
	CSgPtr<CSgMaterial> trackColor = new CSgMaterial();
	trackColor->SetDiffuseColor(.2f, .21f, .23f, 1.f);
	trackColor->SetSpecularColor(.2f, .21f, .23f, 1.f);

	parent->AddChild(trackColor);

	//Create a straight trackA.
	CSgPtr<CSgPolygon> trackStraight = new CSgPolygon();
	trackStraight->AddNormal(CGrVector(0, 1, 0));
	trackStraight->AddVertex3d(-20, 0, 0);
	trackStraight->AddVertex3d(-20, 0, 8);
	trackStraight->AddVertex3d(20, 0, 8);
	trackStraight->AddVertex3d(20, 0, 0);
	trackColor->AddChild(trackStraight);
	//Transform the position of straight trackA to straight trackB.
	CSgPtr<CSgTranslate> transformToTrackB = new CSgTranslate(0,0, -20);

	trackColor->AddChild(transformToTrackB);
	transformToTrackB->AddChild(trackStraight);
	
	//Left & Right Curve tracks
	CSgPtr<CSgTranslate> transformToLeftCurve = new CSgTranslate();
	CSgPtr<CSgTranslate> transformToRightCurve = new CSgTranslate();
	transformToLeftCurve->SetProperties(-20,0,-6);
	transformToRightCurve->SetProperties(20,0,-6);
	
	
	//Start to compute curve track
	double inX1=0,inX2=0,inY1=0,inY2=0,
		   outX1=0,outY1=10,outX2=0,outY2=10;

	CSgPtr<CSgMesh> curveLeft = new CSgMesh();
	transformToLeftCurve->AddChild(curveLeft);//Add the curveLeft fragment as child.
	curveLeft->AddNormal(CGrVector(0, 1, 0));

	CSgPtr<CSgMesh> curveRight = new CSgMesh();
	transformToRightCurve->AddChild(curveRight);//Add the curveRight fragment as child.
	curveRight->AddNormal(CGrVector(0, 1, 0));
	for(int i=0;i<100;i++)
	{
		//Leftside cuve fragments.
		outX1 =  0 + -6 * sin((M_PI/100)*i); //Compute 1st vertex on the outer half circle
		outY1 = 0 + -6 * cos((M_PI/100)*i);
		outX2 =  0 + -6 * sin((M_PI/100)*(i+1)); //Compute 2nd vertex on the outer half circle
		outY2 = 0 + -6 * cos((M_PI/100)*(i+1));
		inX1= 0 + -14 * sin((M_PI/100)*i);  //Compute 1st vertex on the inner half circle
		inY1= 0 + -14 * cos((M_PI/100)*i); 
		inX2= 0 + -14 * sin((M_PI/100)*(i+1));//Compute 2st vertex on the inner half circle
		inY2= 0 + -14 * cos((M_PI/100)*(i+1));
		//four vertex makes a fragment of the curve track.
		/*
		//Code for using polygon instead of mesh
		CSgPtr<CSgPolygon> curveLeft = new CSgPolygon();
		curveLeft->AddNormal(CGrVector(0, 1, 0));
		curveLeft->AddVertex3d(outX2, 0, outY2);
		curveLeft->AddVertex3d(outX1, 0, outY1);
		curveLeft->AddVertex3d(inX1, 0, inY1);
		curveLeft->AddVertex3d(inX2, 0, inY2);
		*/


		curveLeft->AddVertex(CGrVector(outX2, 0, outY2));
		curveLeft->AddVertex(CGrVector(outX1, 0, outY1));
		curveLeft->AddVertex(CGrVector(inX1, 0, inY1));
		curveLeft->AddVertex(CGrVector(inX2, 0, inY2));
		

		
		//Rightside cuve fragments.
		outX1 =  0 + 6 * sin((M_PI/100)*i); //Compute 1st vertex on the outer half circle
		outY1 = 0 + 6 * cos((M_PI/100)*i);
		outX2 =  0 + 6 * sin((M_PI/100)*(i+1)); //Compute 2nd vertex on the outer half circle
		outY2 = 0 + 6 * cos((M_PI/100)*(i+1));
		inX1= 0 + 14 * sin((M_PI/100)*i);  //Compute 1st vertex on the inner half circle
		inY1= 0 + 14 * cos((M_PI/100)*i); 
		inX2= 0 + 14 * sin((M_PI/100)*(i+1));//Compute 2st vertex on the inner half circle
		inY2= 0 + 14 * cos((M_PI/100)*(i+1));
		//four vertex makes a fragment of the curve track.
		/*
		//Code for using polygon instead of mesh
		CSgPtr<CSgPolygon> curveRight = new CSgPolygon();
		curveRight->AddNormal(CGrVector(0, 1, 0));
		curveRight->AddVertex3d(outX2, 0, outY2);
		curveRight->AddVertex3d(outX1, 0, outY1);
		curveRight->AddVertex3d(inX1, 0, inY1);
		curveRight->AddVertex3d(inX2, 0, inY2);
		*/
		curveRight->AddVertex(CGrVector(outX2, 0, outY2));
		curveRight->AddVertex(CGrVector(outX1, 0, outY1));
		curveRight->AddVertex(CGrVector(inX1, 0, inY1));
		curveRight->AddVertex(CGrVector(inX2, 0, inY2));
		
	}
	for(int i=0;i<400;i +=4)
	{
		curveLeft->AddFlatQuad(i, i+1, i+2, i+3, 0);
		curveRight->AddFlatQuad(i, i+1, i+2, i+3, 0);
	}
	trackColor->AddChild(transformToLeftCurve);
	trackColor->AddChild(transformToRightCurve);
	//Curve track computation finished....

	//Code for white bars on the track.
	// bar color
	CSgPtr<CSgMaterial> trackBarColor = new CSgMaterial();
	trackBarColor->SetSpecularColor(1.f,1.f,1.f,1.f);
	trackBarColor->SetDiffuseColor(1.f,1.f,1.f,1.f);
	// Coordinates of bar.
	CSgPtr<CSgPolygon> bar = new CSgPolygon();
	bar->AddNormal(CGrVector(0, 1, 0));
	bar->AddVertex3d(0, 0, 3.5);
	bar->AddVertex3d(0, 0, 4.0);
	bar->AddVertex3d(1, 0, 4.0);
	bar->AddVertex3d(1, 0, 3.5);
	parent->AddChild(trackBarColor);
	for(int n=-20;n<20;n+=3)
	{   // bars for straight track A
		CSgPtr<CSgTranslate> transformBarA = new CSgTranslate();
		transformBarA->SetProperties(n,0.01,0);
		transformBarA->AddChild(bar);
		// bars for straight track B
		CSgPtr<CSgTranslate> transformBarB = new CSgTranslate();
		transformBarB->SetProperties(n,0.01,-20);
		transformBarB->AddChild(bar);
		
		trackBarColor->AddChild(transformBarA);
		trackBarColor->AddChild(transformBarB);
	}
	

}

//
//        Name : CGoCartFactory::Normal3dv()
// Description : Compute the normal of a plan.
//
double *CGoCartFactory::Normal3dv( const double *a,const double *b, const double *c)
{
	double l1[] = {b[0]-a[0], b[1]-a[1], b[2]-a[2]}; 
	double l2[] = {c[0]-a[0], c[1]-a[1], c[2]-a[2]};
	                                          //CrossProduct
	double v[]  = {l1[1]*l2[2]- l2[1]*l1[2],  //x
		           l1[2]*l2[0]-l2[2]*l2[0],   //y
				   l1[0]*l2[1]-l2[0]*l1[1]};  //z

    double tmp= sqrt(v[0] * v[0] + v[1] * v[1] + v[2] * v[2]);
	double *n = new double [3];
	n[0] = v[0]/tmp;
	n[1] = v[1]/tmp;
	n[2] = v[2]/tmp;
	return n;

}